package com.lee.rpc.protocal.spring.reference;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import com.alibaba.fastjson.JSON;
import com.lee.rpc.protocal.constant.RpcConstant;
import com.lee.rpc.protocal.core.Header;
import com.lee.rpc.protocal.core.ReqType;
import com.lee.rpc.protocal.core.RequestHolder;
import com.lee.rpc.protocal.core.RpcFuture;
import com.lee.rpc.protocal.core.RpcProtocal;
import com.lee.rpc.protocal.core.RpcRequest;
import com.lee.rpc.protocal.core.RpcResponse;
import com.lee.rpc.protocal.core.SerialType;
import com.lee.rpc.protocal.netty.NettyClient;

import io.netty.channel.DefaultEventLoop;
import io.netty.util.concurrent.DefaultPromise;

public class RpcInvokeProxy implements InvocationHandler {

	private String serverAddress;
	private int serverPort;
	
	public RpcInvokeProxy(String serverAddress, int serverPort) {
		// TODO Auto-generated constructor stub
		this.serverAddress = serverAddress;
		this.serverPort = serverPort;
	}

	@Override
	public Object invoke(Object arg0, Method method, Object[] args) throws Throwable {
		// TODO Auto-generated method stub
		RpcProtocal<RpcRequest> rpcProtocal = new RpcProtocal<>();
		//构建发送报文
		long requestId = RequestHolder.REQUEST_ID.incrementAndGet();
		
		Header header = new Header(RpcConstant.MAGIC, SerialType.JSON_SERIAL.code(), ReqType.REQUEST.code(), 
				requestId, 0);
		rpcProtocal.setHeader(header);
		
		RpcRequest rpcRequest = new RpcRequest();
		rpcRequest.setClassName(method.getDeclaringClass().getName());
		rpcRequest.setMethodName(method.getName());
		rpcRequest.setParams(args);
		rpcRequest.setParameterTypes(method.getParameterTypes());
		rpcProtocal.setContent(rpcRequest);
		
		//使用Netty发起连接
		NettyClient nettyClient = new NettyClient(serverAddress, serverPort);
		//构建报文
		RpcFuture<RpcResponse> future = new RpcFuture<>(new DefaultPromise<>(new DefaultEventLoop()));
		RequestHolder.REQUEST_MAP.put(requestId, future);
		//发送RPC请求
		nettyClient.sendRequest(rpcProtocal);
		
		//通过promiss异步等待服务端把数据发送过来，不然就会一直等待
		RpcResponse rpcResponse = future.getPromiss().get();
		System.out.println("rpcResponse:"+JSON.toJSON(rpcResponse));
		return rpcResponse.getData();
	}

}
